XML示例


    /*
     * Author: shenjun
     */

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    using UnityEditor;

    using System.Xml;

    public class XML_Operation : MonoBehaviour
    {

        private static XML_Operation instance;

        public static XML_Operation Instance { get { return instance; } }

        string fileName = "Items.xml";

        public string FilePath { get { return Application.streamingAssetsPath + "/" + fileName; } }

        public List<PackageItem> equips = new List<PackageItem>();
        public List<PackageItem> items = new List<PackageItem>();

        #region ContextMenuItem用法

        [ContextMenuItem("ResetXML", "ResetXML")]   // 给该字符串字段添加一个单独的右键菜单 并设置该菜单功能所调用的方法
        [Multiline(4)]   // 使字符串在检视面板显示成几行
        public string SS = "";

        void ResetXML()
        {
            SS = "";
        }

        #endregion

        #region Debug

        [ContextMenuItem("Reset", "ResetEquipsLoaded")]
        public List<PackageItem> equipsLoaded = new List<PackageItem>();

        [ContextMenuItem("Reset", "ResetItemsLoaded")]
        public List<PackageItem> itemsLoaded = new List<PackageItem>();

        void ResetEquipsLoaded()
        {
            equipsLoaded.Clear();
        }

        void ResetItemsLoaded()
        {
            itemsLoaded.Clear();
        }

        void AppendTest()
        {
            // 1. 使用绝对路径的XPath
            //        bool flag = AppendXML("/道具列表/装备", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 2. 开头是两个斜线表示文件中所有符合模式的元素都会被选出来,即使处于树中不同的层级也会被选出来。
            //        bool flag = AppendXML("//装备", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 3. 通配符
            //        bool flag = AppendXML("/*/装备", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 4. 使用方括号可以选择分支 下标从1开始 选择第一个节点
            //        bool flag = AppendXML("/道具列表/装备[1]", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 5. 选择最后一个节点
            //        bool flag = AppendXML("/道具列表/装备[last()]", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 6. 选择所有带有 倚天剑 元素并满足一定层次结构的装备节点
            //        bool flag = AppendXML("/道具列表/装备[倚天剑]", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 7. 选取 价格=1000的节点
            //        bool flag = AppendXML("/道具列表/装备/青铜剑[价格=1000]", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 8. 选取 符合一定层次结构的 装备和道具 节点
            //        bool flag = AppendXML("/道具列表/装备 | /道具列表/道具", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 9. 除了选择元素之外,也可以选择属性 属性都是以 @开头 这里表示选取所有id属性
            //        bool flag = AppendXML("//@id", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 10. 选取所有道具节点下 具有id属性的节点
            //        bool flag = AppendXML("//道具/*[@id]", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 11. 选取所有道具节点下 具有id属性 并且id属性等于12的节点
            //        bool flag = AppendXML("//道具/*[@id=12]", new PackageItem(){ id = "4", name = "铁剑", price = 500 });

            // 12. 通过节点名查找
            bool flag = AppendXML("大还丹", new PackageItem(){ id = "4", name = "铁剑", price = 500 }, true);
            if (!flag)
                Debug.Log("插入失败");
        }

        void RemoveTest()
        {
            //        bool flag = RemoveXML("//*[@id=12]");

            //        bool flag = RemoveXML("/道具列表/装备/倚天剑");

            //        bool flag = RemoveXML("/道具列表/装备/*[价格=1000]");

            bool flag = RemoveXML("屠龙刀", true);
            if (!flag)
                Debug.Log("删除失败");
        }

        void ModifyTest()
        {
            bool flag = ModifyXML("//*[@id=12]/价格", "2000");

            if (!flag)
            {
                Debug.Log("修改失败");
            }
        }

        void GetXMLNodeTest()
        {
            List<PackageItem> items;
    //        items = GetXMLNode("//*[@id=11]");

            items = GetXMLNode("青铜剑", true);
            foreach (var item in items)
            {
                Debug.Log("Name :" + item.name);
                Debug.Log("Id : " + item.id);
                Debug.Log("Price : " + item.price);
            }
        }

        #endregion


        void Awake()
        {
            instance = this;
        }

        void Start()
        {
    //        AppendTest();
    //        RemoveTest();
    //        ModifyTest();
    //        GetXMLNodeTest();
        }



        public List<PackageItem> GetXMLNode(string xpath, bool byTag = false)
        {
            if (!System.IO.File.Exists(FilePath))
                return null;

            List<PackageItem> nodesList = new List<PackageItem>();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(FilePath);
            XmlNodeList nodes;
            if (byTag)
            {
                nodes = xmlDoc.GetElementsByTagName(xpath);
            }
            else
            {
                nodes = xmlDoc.SelectNodes(xpath);
            }
            foreach (XmlElement n in nodes)
            {
                PackageItem item = new PackageItem();
                item.name = n.Name;
                if (n.HasAttribute("id"))
                {
                    item.id = n.GetAttribute("id");
                }
                if (n.HasChildNodes)
                {
                    int.TryParse(n.FirstChild.InnerText, out item.price);
                }
                nodesList.Add(item);
            }
            return nodesList;
        }

        [ContextMenu("生成道具XML文件")]
        void CreateXML()
        {
            if (System.IO.File.Exists(FilePath))
            {
                System.IO.File.Delete(FilePath);
            }

            XmlDocument xmlDoc = new XmlDocument();
            XmlDeclaration xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
            xmlDoc.AppendChild(xmlDec);

            // 只允许有一个根节点
            XmlElement root = xmlDoc.CreateElement("道具列表");


            if (equips.Count > 0)
            {
                XmlElement xmlEquip = xmlDoc.CreateElement("装备");

                foreach (var item in equips)
                {
                    XmlElement name = xmlDoc.CreateElement(item.name);
                    name.SetAttribute("id", item.id);

                    XmlElement price = xmlDoc.CreateElement("价格");
                    price.InnerText = item.price.ToString();


                    xmlEquip.AppendChild(name);
                    name.AppendChild(price);
                }

                root.AppendChild(xmlEquip);
            }

            if (items.Count > 0)
            {
                XmlElement xmlItem = xmlDoc.CreateElement("道具");
                foreach (var item in items)
                {

                    XmlElement name = xmlDoc.CreateElement(item.name);
                    name.SetAttribute("id", item.id);

                    XmlElement price = xmlDoc.CreateElement("价格");
                    price.InnerText = item.price.ToString();

                    xmlItem.AppendChild(name);
                    name.AppendChild(price);
                }

                root.AppendChild(xmlItem);
            }

            xmlDoc.AppendChild(root);
            xmlDoc.Save(FilePath);

            #if UNITY_EDITOR
            AssetDatabase.Refresh();
            #endif
        }

        [ContextMenu("载入XML文件")]
        void LoadXML()
        {
            equipsLoaded.Clear();
            itemsLoaded.Clear();

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(FilePath);

    //        XmlElement root = xmlDoc.DocumentElement;
    //        Debug.Log("Root : " + root.Name);

            // XPath的开头是一个斜线代表这是绝对路径,可以选出所有路径符合这个模式的元素。
            XmlNode node = xmlDoc.SelectSingleNode("/道具列表/装备");
            XmlNodeList pNodeList = node.ChildNodes;
            foreach (var item in pNodeList)
            {
                XmlElement element = item as XmlElement;
                if (element != null)
                {
                    PackageItem equip = new PackageItem();
                    equip.name = element.Name;
                    equip.id = element.GetAttribute("id");
                    equip.price = int.Parse(element.InnerText);
                    equipsLoaded.Add(equip);
                }
            }

            node = xmlDoc.SelectSingleNode("/道具列表/道具");
            pNodeList = node.ChildNodes;
            foreach (var item in pNodeList)
            {
                XmlElement element = item as XmlElement;
                if (element != null)
                {
                    PackageItem equip = new PackageItem();
                    equip.name = element.Name;
                    equip.id = element.GetAttribute("id");
                    equip.price = int.Parse(element.InnerText);
                    itemsLoaded.Add(equip);
                }
            }
        }

        public bool AppendXML(string xpath, PackageItem item, bool byTag = false)
        {
            if (!System.IO.File.Exists(FilePath))
                return false;

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(FilePath);

            XmlNodeList nodes;
            if (byTag)
            {
                nodes = xmlDoc.GetElementsByTagName(xpath);
            }
            else
            {
                nodes = xmlDoc.SelectNodes(xpath);
            }

            if (nodes == null || nodes.Count == 0)
                return false;

            // 测试第9点 获取所有满足条件的属性
    //        foreach (XmlAttribute n in nodes) 
    //        {
    //            Debug.Log(n.Value);
    //            Debug.Log(n.OwnerElement.Name);
    //        }

            foreach (XmlElement node in nodes)
            {
                XmlElement name = xmlDoc.CreateElement(item.name);
                name.SetAttribute("id", item.id);
                XmlElement price = xmlDoc.CreateElement("价格");
                price.InnerText = item.price.ToString();
                name.AppendChild(price);

                node.AppendChild(name);
            }

            xmlDoc.Save(FilePath);  // 保存
            return true;
        }

        public bool RemoveXML(string xpath, bool byTag = false)
        {
            if (!System.IO.File.Exists(FilePath))
                return false;

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(FilePath);

            XmlNodeList nodes;
            if (byTag)
            {
                nodes = xmlDoc.GetElementsByTagName(xpath);
            }
            else
            {
                nodes = xmlDoc.SelectNodes(xpath);
            }

            if (nodes == null || nodes.Count == 0)
                return false;

            for (int i = 0; i < nodes.Count; i++)
            {
                Debug.Log("删除节点:" + nodes[i].Name);
                nodes[i].ParentNode.RemoveChild(nodes[i]);
            }

            xmlDoc.Save(FilePath);
            return true;
        }

        public bool ModifyXML(string xpath, string value)
        {
            if (!System.IO.File.Exists(FilePath))
                return false;

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(FilePath);

            XmlNodeList nodes = xmlDoc.SelectNodes(xpath);

            if (nodes == null || nodes.Count == 0)
                return false;

            foreach (XmlElement n in nodes)
            {
                n.InnerText = value;
            }

            xmlDoc.Save(FilePath);
            return true;
        }

    }

    [System.Serializable]
    public struct PackageItem
    {
        public string id;
        public string name;
        public int price;
    }